﻿namespace ScrumLite.WebUx.Handlers
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text.RegularExpressions;
    using System.Web;

    public class JSCombineHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { return false; }
        }

        public void ProcessRequest(HttpContext context)
        {
            if (!string.IsNullOrEmpty(context.Request.QueryString["js"]))
            {
                string[] relativeFiles = context.Request.QueryString["js"].Split(',');
                List<string> absoluteFiles = new List<string>();

                for (int i = 0; i < relativeFiles.Length; i++)
                {
                    string file = relativeFiles[i];
                    if (file.EndsWith(".js", StringComparison.OrdinalIgnoreCase))
                    {
                        string absoluteFile = context.Server.MapPath(file);
                        if (File.Exists(absoluteFile))
                        {
                            WriteContent(context, absoluteFile);
                            absoluteFiles.Add(absoluteFile);
                        }
                    }
                }

                SetHeaders(context, absoluteFiles.ToArray());
            }
        }

        /// <summary>
        /// Writes the content of the individual javascript files to the response stream.
        /// </summary>
        private static void WriteContent(HttpContext context, string file)
        {
            using (StreamReader reader = new StreamReader(file))
            {
                string body = StripWhitespace(reader.ReadToEnd());
                context.Response.Write(body);
                context.Response.Write("\n");
            }
        }

        /// <summary>
        /// Strips the whitespace from any .js file.
        /// </summary>
        private static string StripWhitespace(string body)
        {
            string optimized = Regex.Replace(body, @"/\*.*?\*/\s*\n*", string.Empty, RegexOptions.Singleline);
            return Regex.Replace(optimized, @"^\s*//.*$\n?|^\s*$\n|^\s+|\s+$", string.Empty, RegexOptions.Multiline);
        }

        /// <summary>
        /// This will make the browser and server keep the output
        /// in its cache and thereby improve performance.
        /// </summary>
        private static void SetHeaders(HttpContext context, string[] files)
        {
            context.Response.ContentType = "text/javascript";
            context.Response.AddFileDependencies(files);
            context.Response.Cache.VaryByParams["js"] = true;
            context.Response.Cache.SetETagFromFileDependencies();
            context.Response.Cache.SetLastModifiedFromFileDependencies();
            context.Response.Cache.SetValidUntilExpires(true);
            context.Response.Cache.SetExpires(DateTime.Now.AddDays(7));
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
        }

    }
}
